package com.db.williamchart.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.db.williamchart.ChartContract;
import com.db.williamchart.ExperimentalFeature;
import com.db.williamchart.R;
import com.db.williamchart.animation.NoAnimation;
import com.db.williamchart.data.AxisType;
import com.db.williamchart.data.Frame;
import com.db.williamchart.data.Label;
import com.db.williamchart.data.Paddings;
import com.db.williamchart.data.Scale;
import com.db.williamchart.data.configuration.BarChartConfiguration;
import com.db.williamchart.data.configuration.ChartConfiguration;
import com.db.williamchart.extensions.ExtensionUtils;
import com.db.williamchart.renderer.BarChartRenderer;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

public class BarChartView extends AxisChartView implements ChartContract.BarView {
    private final float defaultSpacing = 10f;
    private final int defaultBarsColor = Color.BLACK;
    private final float defaultBarsRadius = 0F;

    private float spacing = defaultSpacing;

    @ColorInt
    private int barsColor = defaultBarsColor;

    @ExperimentalFeature
    private List<Integer> barsColorsList = null;

    private float barRadius = defaultBarsRadius;

    private int barsBackgroundColor = -1;

    public BarChartView(@NonNull Context context) {
        this(context, null);
    }

    public BarChartView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BarChartView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @SuppressLint("CustomViewStyleable")
    private void init(@NonNull Context context, @Nullable AttributeSet attrs) {
        renderer = new BarChartRenderer(this, painter, new NoAnimation());
        handleAttributes(context.obtainStyledAttributes(attrs, R.styleable.BarChartAttrs));
        handleEditMode();
    }

    @Override
    ChartConfiguration getChartConfiguration() {

        return new BarChartConfiguration(
                getMeasuredWidth(),
                getMeasuredHeight(),
                new Paddings(
                        getPaddingLeft(),
                        getPaddingTop(),
                        getPaddingRight(),
                        getPaddingBottom()
                ),
                axis,
                labelsSize,
                scale,
                labelsFormatter,
                barsBackgroundColor,
                spacing
        );
    }

    @Override
    public void drawBars(List<Frame> frames) {
        if (barsColorsList == null) {
            List<Integer> colors = new ArrayList<>();
            for (int i = 0; i < frames.size(); i++) {
                colors.add(barsColor);
            }
            barsColorsList = colors;
        }

        if (barsColorsList.size() != frames.size()) {
            throw new IllegalArgumentException("Colors provided do not match the number of datapoints.");
        }

        for (int i = 0; i < frames.size(); i++) {
            painter.prepare(barsColorsList.get(i), Paint.Style.FILL);
            ExtensionUtils.drawChartBar(canvas,
                    frames.get(i).toRectF(),
                    barRadius,
                    painter.getPaint());
        }
    }

    @Override
    public void drawBarsBackground(List<Frame> frames) {
        painter.prepare(barsBackgroundColor, Paint.Style.FILL);
        for (Frame frame : frames) {
            ExtensionUtils.drawChartBar(
                    canvas,
                    frame.toRectF(),
                    barRadius,
                    painter.getPaint()
            );
        }
    }

    @Override
    public void drawLabels(List<Label> xLabels) {
        painter.prepare(labelsSize, labelsColor, labelsFont);
        labels.draw(canvas, painter.getPaint(), xLabels);
    }

    @Override
    public void drawGrid(Frame innerFrame, List<Float> xLabelsPositions, List<Float> yLabelsPositions) {
        grid.draw(canvas, innerFrame, xLabelsPositions, yLabelsPositions);
    }

    @Override
    public void drawDebugFrame(List<Frame> frames) {

        painter.prepare(-0x1000000, Paint.Style.STROKE);
        for (Frame frame : frames) {
            canvas.drawRect(frame.toRect(), painter.getPaint());
        }
    }

    private void handleAttributes(TypedArray typedArray) {
        spacing = typedArray.getDimension(R.styleable.BarChartAttrs_chart_spacing, spacing);
        barsColor = typedArray.getColor(R.styleable.BarChartAttrs_chart_barsColor, barsColor);
        barRadius = typedArray.getDimension(R.styleable.BarChartAttrs_chart_barsRadius, barRadius);
        barsBackgroundColor =
                typedArray.getColor(R.styleable.BarChartAttrs_chart_barsBackgroundColor, barsBackgroundColor);
        int resourceId = typedArray.getResourceId(R.styleable.BarChartAttrs_chart_barsColorsList, -1);
        if (resourceId != -1) {
            int[] array = typedArray.getResources().getIntArray(resourceId);
            for (int value : array) {
                barsColorsList.add(value);
            }
        }
        typedArray.recycle();
    }
}
